#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
自动应用 AI 诊断建议的修复
"""
import json
import sys
import argparse
from pathlib import Path
from typing import Dict, List, Any


class FixApplicator:
    """修复应用器"""

    def __init__(self, dry_run: bool = True):
        """
        初始化修复应用器

        Args:
            dry_run: 如果为 True，只显示修复但不实际应用
        """
        self.dry_run = dry_run
        self.applied_fixes = []
        self.failed_fixes = []

    def apply_fixes_from_report(self, report_path: Path) -> Dict[str, Any]:
        """
        从诊断报告应用修复

        Args:
            report_path: 诊断报告路径

        Returns:
            应用结果统计
        """
        if not report_path.exists():
            raise FileNotFoundError(f"Diagnostic report not found: {report_path}")

        with open(report_path, "r", encoding="utf-8") as f:
            report = json.load(f)

        # 提取修复建议
        fixes = self._extract_fixes_from_report(report)

        print(f"[FixApplicator] 找到 {len(fixes)} 个修复建议")
        if self.dry_run:
            print("[FixApplicator] DRY RUN 模式 - 不会实际修改文件")
        print()

        # 应用每个修复
        for i, fix in enumerate(fixes, 1):
            print(f"[{i}/{len(fixes)}] 应用修复: {fix['description']}")
            success = self._apply_single_fix(fix)

            if success:
                self.applied_fixes.append(fix)
                print(f"  ✓ 成功")
            else:
                self.failed_fixes.append(fix)
                print(f"  ✗ 失败")
            print()

        # 返回统计
        return {
            "total": len(fixes),
            "applied": len(self.applied_fixes),
            "failed": len(self.failed_fixes),
            "dry_run": self.dry_run
        }

    def _extract_fixes_from_report(self, report: Dict[str, Any]) -> List[Dict[str, Any]]:
        """从诊断报告提取修复建议"""
        fixes = []

        # 尝试从不同的报告格式提取修复
        if "analysis" in report and "recommended_actions" in report["analysis"]:
            for action in report["analysis"]["recommended_actions"]:
                if isinstance(action, dict) and "type" in action:
                    fixes.append(action)

        # 如果没有结构化修复，尝试从文本生成简单修复
        if not fixes and "analysis" in report:
            # 这里可以添加更多的解析逻辑
            pass

        return fixes

    def _apply_single_fix(self, fix: Dict[str, Any]) -> bool:
        """
        应用单个修复

        Args:
            fix: 修复定义

        Returns:
            True if successful, False otherwise
        """
        fix_type = fix.get("type", "unknown")

        try:
            if fix_type == "code_replacement":
                return self._apply_code_replacement(fix)
            elif fix_type == "config_update":
                return self._apply_config_update(fix)
            elif fix_type == "file_creation":
                return self._apply_file_creation(fix)
            elif fix_type == "import_fix":
                return self._apply_import_fix(fix)
            else:
                print(f"  [FixApplicator] 未知修复类型: {fix_type}")
                return False
        except Exception as e:
            print(f"  [FixApplicator] 错误: {e}")
            return False

    def _apply_code_replacement(self, fix: Dict[str, Any]) -> bool:
        """应用代码替换修复"""
        file_path = Path(fix["file"])
        old_code = fix["old_code"]
        new_code = fix["new_code"]

        if not file_path.exists():
            print(f"  [FixApplicator] 文件不存在: {file_path}")
            return False

        content = file_path.read_text(encoding="utf-8")

        if old_code not in content:
            print(f"  [FixApplicator] 未找到旧代码")
            return False

        if self.dry_run:
            print(f"  [FixApplicator] 将替换: {old_code[:50]}...")
            print(f"  [FixApplicator] 替换为: {new_code[:50]}...")
            return True

        # 实际应用修复
        new_content = content.replace(old_code, new_code)
        file_path.write_text(new_content, encoding="utf-8")
        return True

    def _apply_config_update(self, fix: Dict[str, Any]) -> bool:
        """应用配置更新"""
        config_file = Path(fix["file"])
        updates = fix.get("updates", {})

        if self.dry_run:
            print(f"  [FixApplicator] 将更新配置: {config_file}")
            for key, value in updates.items():
                print(f"    {key} = {value}")
            return True

        # 实际应用配置更新（需要根据文件类型实现）
        if config_file.suffix == ".yaml":
            return self._update_yaml_config(config_file, updates)
        elif config_file.suffix == ".toml":
            return self._update_toml_config(config_file, updates)
        else:
            print(f"  [FixApplicator] 不支持的配置文件类型: {config_file.suffix}")
            return False

    def _apply_file_creation(self, fix: Dict[str, Any]) -> bool:
        """创建新文件"""
        file_path = Path(fix["file"])
        content = fix["content"]

        if file_path.exists():
            print(f"  [FixApplicator] 文件已存在: {file_path}")
            return False

        if self.dry_run:
            print(f"  [FixApplicator] 将创建文件: {file_path}")
            print(f"  [FixApplicator] 内容长度: {len(content)} 字符")
            return True

        # 创建目录（如果不存在）
        file_path.parent.mkdir(parents=True, exist_ok=True)

        # 写入文件
        file_path.write_text(content, encoding="utf-8")
        return True

    def _apply_import_fix(self, fix: Dict[str, Any]) -> bool:
        """修复导入问题"""
        file_path = Path(fix["file"])
        missing_import = fix["import"]

        if not file_path.exists():
            return False

        content = file_path.read_text(encoding="utf-8")

        # 检查导入是否已存在
        if missing_import in content:
            print(f"  [FixApplicator] 导入已存在")
            return True

        if self.dry_run:
            print(f"  [FixApplicator] 将添加导入: {missing_import}")
            return True

        # 在文件开头添加导入
        lines = content.split('\n')
        import_line_idx = 0

        # 找到最后一个导入语句的位置
        for i, line in enumerate(lines):
            if line.startswith('import ') or line.startswith('from '):
                import_line_idx = i + 1

        # 插入新导入
        lines.insert(import_line_idx, missing_import)
        new_content = '\n'.join(lines)

        file_path.write_text(new_content, encoding="utf-8")
        return True

    def _update_yaml_config(self, config_file: Path, updates: Dict[str, Any]) -> bool:
        """更新 YAML 配置"""
        try:
            import yaml
            with open(config_file, "r", encoding="utf-8") as f:
                config = yaml.safe_load(f)

            # 应用更新
            for key, value in updates.items():
                keys = key.split('.')
                current = config
                for k in keys[:-1]:
                    current = current.setdefault(k, {})
                current[keys[-1]] = value

            with open(config_file, "w", encoding="utf-8") as f:
                yaml.dump(config, f, allow_unicode=True, default_flow_style=False)

            return True
        except Exception as e:
            print(f"  [FixApplicator] YAML 更新失败: {e}")
            return False

    def _update_toml_config(self, config_file: Path, updates: Dict[str, Any]) -> bool:
        """更新 TOML 配置"""
        try:
            import tomli
            import tomli_w

            with open(config_file, "rb") as f:
                config = tomli.load(f)

            # 应用更新
            for key, value in updates.items():
                keys = key.split('.')
                current = config
                for k in keys[:-1]:
                    current = current.setdefault(k, {})
                current[keys[-1]] = value

            with open(config_file, "wb") as f:
                tomli_w.dump(config, f)

            return True
        except Exception as e:
            print(f"  [FixApplicator] TOML 更新失败: {e}")
            return False


def main():
    parser = argparse.ArgumentParser(description="应用 AI 诊断修复建议")
    parser.add_argument(
        "--report",
        default="reports/ai_diagnostic_latest.json",
        help="诊断报告路径"
    )
    parser.add_argument(
        "--apply",
        action="store_true",
        help="实际应用修复（默认为 dry-run 模式）"
    )

    args = parser.parse_args()

    # 创建修复应用器
    applicator = FixApplicator(dry_run=not args.apply)

    # 应用修复
    report_path = Path(args.report)
    try:
        result = applicator.apply_fixes_from_report(report_path)

        print("=" * 60)
        print("修复应用结果:")
        print(f"  总计: {result['total']}")
        print(f"  成功: {result['applied']}")
        print(f"  失败: {result['failed']}")

        if result['dry_run']:
            print("\n💡 这是 DRY RUN 模式，文件未被修改")
            print("使用 --apply 参数实际应用修复")

        return 0 if result['failed'] == 0 else 1

    except FileNotFoundError as e:
        print(f"[FixApplicator] 错误: {e}")
        return 1
    except Exception as e:
        print(f"[FixApplicator] 未预期的错误: {e}")
        return 1


if __name__ == "__main__":
    sys.exit(main())
